<?php
/**
 * NotificationRepo.php
 *
 * @copyright   2023 thingsworld.com.cn - All Rights Reserved
 * @link        http://thingsworld.com.cn/
 * @author      stiffer.chen <chenl@thingsworld.com.cn>
 * @created     2023-02-19 16:00:30
 * @modified    2023-02-19 16:00:30
 *
 */

namespace App\Repositories;

use App\Library\Logger;
use App\Models\InventoryAllot;
use App\Models\Notification;
use App\Models\Polling;
use App\Models\Project\Task;
use App\Models\QuestionFeedback;
use App\Models\Suggest;
use App\Models\User;
use App\Models\UserModel;
use App\Services\Push\GeTuiService;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class NotificationRepo
{
    const PLATFORM_WEB = 'web';
    const PLATFORM_ANDROID = 'android';
    const PLATFORM_IOS = 'ios';
    const PLATFORM_MINI_APP = 'mini_app';

    const TYPE_WORK_ORDER = 'work_order'; // 工单
    const TYPE_EVENT = 'event'; // 事件
    const TYPE_TASK = 'task'; // 任务
    const TYPE_INVENTORY = 'inventory'; // 备件
    const TYPE_SUGGEST = 'suggest'; // 意见反馈
    const TYPE_QUESTION_FEEDBACK = 'question_feedback'; // 问题反馈
    const TYPE_POLLING = 'polling'; // 巡检任务

    public static function getList()
    {
        $perPage = (int)request('limit');
        if ($perPage < 1) {
            $perPage = 10;
        }
        $userId = registry('user_id') ?? 0;
        $builder = Notification::query();
        if ($userId != 1) {
            $user = registry('user');
            if (!$user->isServiceManager()) {
                $builder->where('user_id', $userId);
            }
        }
        $type = request()->get('type') ?? '';
        if (in_array($type, [self::TYPE_WORK_ORDER, self::TYPE_EVENT, self::TYPE_TASK, self::TYPE_INVENTORY, self::TYPE_SUGGEST, self::TYPE_QUESTION_FEEDBACK, self::TYPE_POLLING])) {
            $builder->where('business_type', $type);
        }
        $builder->orderByDesc('id');
        $result = $builder->paginate($perPage);
        $result->transform(function ($item) {
            $type = $item->business_type;
            if ($type == self::TYPE_TASK) {
                return self::detailTask($item);
            } elseif ($type == self::TYPE_INVENTORY) {
                return self::detailInventory($item);
            } elseif ($type == self::TYPE_SUGGEST) {
                return self::detailSuggest($item);
            } elseif ($type == self::TYPE_QUESTION_FEEDBACK) {
                return self::detailQuestionFeedback($item);
            } elseif ($type == self::TYPE_POLLING) {
                return self::detailPolling($item);
            }
            return $item;
        });
        return $result;
    }

    private static function detailPolling($item)
    {
        $pId = $item->business_id;
        $polling = Polling::find($pId);

        return [
            'id' => $item->id,
            'business_id' => $item->business_id,
            'business_type' => $item->business_type,
            'title' => $item->title,
            'customer_name' => $polling->customer_name ?? '',
            'customer_user_name' => $polling->customer_user_name ?? '',
            'customer_user_telephone' => $polling->customer_user_telephone ?? '',
            'customer_address' => $polling->customer_address ?? '',
            'user_id' => $polling->user_id ?? 0,
            'user_name' => $polling->user_name ?? '',
            'plan_at' => $polling->plan_at ?? '',
            'status' => $item->status ?? 0,
            'create_time' => Carbon::parse($item->create_time)->toDateTimeString()
        ];
    }

    private static function detailQuestionFeedback($item)
    {
        $commentArr = json_decode($item->comment, true);
        $qf = QuestionFeedback::find($item->business_id);
        if ($qf->wo_id) {
            $source = '工单反馈';
        } else {
            $source = '项目反馈';
        }
        return [
            'id' => $item->id,
            'business_id' => $item->business_id,
            'business_type' => $item->business_type,
            'user_id' => $qf->user_id ?? 0,
            'user_name' => $qf->user_name ?? '',
            'title' => $item->title,
            'content' => $item->content,
            'source' => $source,
            'status' => $item->status ?? 0,
            'actor_role_name' => $commentArr['actor_role_name'],
            'actor_user_name' => $commentArr['actor_user_name'],
            'create_time' => Carbon::parse($item->create_time)->toDateTimeString()
        ];
    }

    private static function detailSuggest($item)
    {
        $suggest = Suggest::find($item->business_id);
        $allStatus = SuggestRepo::status();
        return [
            'id' => $item->id,
            'business_id' => $item->business_id,
            'business_type' => $item->business_type,
            'title' => $suggest->title,
            'create_user_name' => $suggest->create_user->realname ?? '',
            'charge_user_name' => $suggest->charge_user->realname ?? '',
            'project_name' => $suggest->project->name ?? '',
            'level' => $suggest->level,
            'status' => $item->status ?? 0,
            'status_text' => $allStatus[$suggest->status] ?? '',
            'create_time' => Carbon::parse($suggest->create_time)->toDateTimeString()
        ];
    }

    private static function detailInventory($item) {
        $allot = InventoryAllot::find($item->business_id);
        return [
            'id' => $item->id,
            'business_id' => $item->business_id,
            'business_type' => $item->business_type,
            'inventory_type' => $allot->type,
            'number' => $allot->number,
            'title' => $item->title,
            'source_warehouse_name' => $allot->source_warehouse->name ?? '',
            'target_warehouse_name' => $allot->target_warehouse_name ?? '',
            'target_username' => $allot->target_user->realname ?? '',
            'create_username' => $allot->user->realname ?? '',
            'status' => $item->status ?? 0,
            'create_time' => Carbon::parse($allot->create_time)->toDateTimeString()
        ];
    }

    private static function detailTask($item)
    {
        $taskId = $item->business_id;
        $task = Task::find($taskId);
        $users = $task->users;
        $usersArr = [];
        foreach ($users as $user) {
            $usersArr[] = $user->user->realname ?? '';
        }
        return [
            'id' => $item->id ?? '',
            'cid' => $item->cid ?? '',
            'platform' => $item->platform ?? '',
            'title' => $item->title,
            'business_id' => $taskId,
            'business_type' => $item->business_type,
            'task_number' => $task->task_number ?? '',
            'project_id' => $task->project->id ?? 0,
            'project_name' => $task->project->name ?? '',
            'project_number' => $task->project->project_number ?? '',
            'plan_start_at' => $task->plan_start_at ?? '',
            'create_time' => Carbon::parse($item->create_time)->toDateTimeString(),
            'status' => $item->status ?? 0,
            'users' => implode(',', $usersArr)
        ];
    }

    public static function statusCount()
    {
        $userId = intval(registry('user_id') ?? 0);
        $query = Notification::query();
        if ($userId != 1) {
            $query->where('user_id', $userId);
        }
        $counts = $query
            ->select(DB::raw('count("*") as count'), 'status')
            ->groupBy('status')
            ->get()
            ->keyBy('status')
            ->toArray();
        return [
            'read' => $counts[1]['count'] ?? 0,
            'unread' => $counts[0]['count'] ?? 0
        ];
    }

    public static function markRead($id)
    {
        $notification = Notification::find($id);
        if (empty($notification)) {
            throw new \Exception('通知不存在');
        }
        if ($notification->status) {
            return self::fetch($id);
        }
        $notification->status = 1;
        $notification->saveOrFail();
        return self::fetch($id);
    }

    public static function fetch($id)
    {
        $notification = Notification::find($id);
        if (empty($notification)) {
            throw new \Exception('通知不存在');
        }
        return $notification;
    }

    // 批量存储
    public static function multiStore($userIds, int $businessId, string $businessType, string $title, string $content, string $comment = '')
    {
        $log = new Logger('notify');
        if (empty($userIds)) {
            $log->error("推送失败， 无推送对象， 业务ID: {$businessId}, 业务类型: {$businessType}, 标题: {$title}, 内容: {$content}");
            return;
        }
        $userIds = array_unique($userIds);
        foreach ($userIds as $userId) {
            self::store($userId, $businessId, $businessType, $title, $content, $comment);
        }
    }

    // 标记所有为已读
    public static function readAll()
    {
        $userId = registry('user_id');
        Notification::query()->where('user_id', '=', $userId)->update(['status' => 1]);
    }

    /**
     * 存储通知
     *
     * @param int $userId 接收通知的用户ID
     * @param int $businessId 业务ID
     * @param string $businessType 业务类型
     * @param string $title 通知标题
     * @param string $content 通知内容
     * @throws \Throwable
     */
    public static function store(int $userId, int $businessId, string $businessType, string $title, string $content, string $comment = '')
    {
        $data = [
            'user_id' => $userId,
            'title' => $title,
            'business_id' => $businessId,
            'business_type' => $businessType,
            'content' => $content,
            'comment' => $comment,
            'create_user_id' => intval(registry('user_id') ?? 0),
            'status' => 0,
        ];
        $logger = new Logger('notify');

        $logger->error("推送数据: 业务ID: {$businessId}, 业务类型: {$businessType}, 标题: {$title}, 内容: {$content}");

        $notification = new Notification();
        $notification->fill($data);
        $notification->saveOrFail();
        self::send($userId, $notification->id);
    }

    public static function send($userId, $notifyId)
    {
        $userIds = [$userId];
        (new GeTuiService($userIds, $notifyId))->push();
    }
}